#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>

//uprintf for debug
#include <sys/systm.h>

#include "uln_adapter.h"


//For PCI
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>

//For USB
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>


#define ULN_DEBUG 1

#define uln_printf(fmt, msg...) \
    do{ \
        if( ULN_DEBUG ) \
            uprintf("[%s:%d]"fmt"\n",__FILE__,__LINE__,##msg); \
    }while(0)


//==========可加载模块声明==========
static int uln_modevent(module_t mod, int event, void *arg);
static moduledata_t uln_mod = {
    "uln",
    uln_modevent,
    NULL
};
DECLARE_MODULE(uln, uln_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);

//============NewBUS声明=============
static int uln_probe(device_t dev);
static int uln_attach(device_t dev);
static int uln_detach(device_t dev);

static device_method_t uln_usb_methods[]={
    DEVMETHOD(device_probe,     uln_probe),
    DEVMETHOD(device_attach,    uln_attach),
    DEVMETHOD(device_detach,    uln_detach),
    {0,0},
};

static driver_t uln_usb_driver = {
    "uln_usb",
    uln_usb_methods,
    sizeof(struct uln_softc),
};

static devclass_t uln_usb_devclass;

DRIVER_MODULE(uln, pci, uln_usb_driver, uln_usb_devclass, 0, 0);

//============USB接口声明===============

enum 
{
    ULN_BULK_DT_WR,
    ULN_BUIL_DT_RD,
    ULN_INTR_DT_RD,
    ULN_N_TRANSFER
};

#define ULN_BUF_SIZE     (1 << 15)

static usb_fifo_open_t  uln_open;
static usb_fifo_close_t uln_close;
static usb_fifo_cmd_t   uln_start_read;
static usb_fifo_cmd_t   uln_start_write;
static usb_fifo_cmd_t   uln_stop_read;
static usb_fifo_cmd_t   uln_stop_write;


static usb_callback_t   uln_read_callback;
static usb_callback_t   uln_write_callback;
static usb_callback_t   uln_status_callback;

static struct usb_fifo_methods uln_fifo_methods ={
    .f_open         =   &uln_open,
    .f_close        =   &uln_close,
    .f_start_read   =   &uln_start_read,
    .f_stop_read    =   &uln_stop_read,
    .f_start_write  =   &uln_start_write,
    .f_stop_write   =   &uln_stop_write,
    .basename[0]    = "uln",
};

static const struct usb_config uln_config[ULN_N_TRANSFER ] ={
    [ULN_BULK_DT_WR]    =   {
        .callback   =   &uln_write_callback,
        .bufsize    =   ULN_BUF_SIZE,
        .flags      =   {.pipe_bof = 1, .proxy_buffer = 1},
        .type       =   UE_BULK,
        .endpoint   =   UE_ADDR_ANY,
        .direction  =   UE_DIR_OUT,
    },

    [ULN_BUIL_DT_RD]    =   {
        .callback   =   &uln_read_callback,
        .bufsize    =   ULN_BUF_SIZE,
        .flags      =   {.short_xfer_ok = 1, .pipe_bof =1, .proxy_buffer = 1},
        .type       =   UE_BULK,
        .endpoint   =   UE_ADDR_ANY,
        .direction  =   UE_DIR_ANY,
    },

    [ULN_INTR_DT_RD]    =   {
        .callback   =   &uln_status_callback,
        .bufsize    =   sizeof(struct usb_device_request) + 1,
        .timeout    =   1000, /*second*/
        .type       =   UE_CONTROL,
        .endpoint   =   0x00,
        .direction  =   UE_DIR_ANY,
    }
};

//==========可加载模块实现============
int uln_modevent(module_t mod __unused, int event, void *arg __unused)
{
    int error = 0;
    switch( event )
    {
        case MOD_LOAD:
            uln_printf("MOD_LOAD OK!");
            break;

        case MOD_UNLOAD:
            uln_printf("MOD_UNLOAD OK!");
            break;

        case MOD_SHUTDOWN:
            break;

        case MOD_QUIESCE:
            break;

        default:
            break;
    }
    return error;
}

//============NewBUS实现=============
static int uln_probe(device_t dev)
{
    /*
    uint32_t type = pci_get_devid(dev);
    uln_printf("type:%#X", type);
    return ENXIO;
    */

    struct usb_attach_arg *uaa = device_get_ivars(dev);

    uln_printf("usb_mode:%d, Class:%d, SubClass:%d, FaceProtocol:%d",
            uaa->usb_mode, uaa->info.bInterfaceClass, 
            uaa->info.bInterfaceSubClass, uaa->info.bInterfaceProtocol);
    return ENXIO;
}


static int uln_attach(device_t dev)
{
    /*
    struct usb_attahc_argv *uaa = device_get_ivars(dev);
    
    usb_fifo_attach(uaa->device, NULL, NULL, &uln_fifo_methods, NULL, 0, -1, 1, UID_ROOT, GID_OPERATOR, 0644);
    */

    uln_printf("sizeof(uln_fifo_methods):%ld", sizeof(uln_fifo_methods));
    return 0;
}

static int uln_detach(device_t dev)
{
    return 0;
}

//===========USB实现=================
int uln_open(struct usb_fifo *fifo, int fflags)
{
    uln_printf("OK");
    return 0;
}

void uln_close(struct usb_fifo *fifo, int fflags)
{
    uln_printf("OK");
}

void uln_start_read(struct usb_fifo *fifo)
{
    uln_printf("OK");
}

void uln_start_write(struct usb_fifo *fifo)
{
    uln_printf("OK");
}

void uln_stop_read(struct usb_fifo *fifo)
{
    uln_printf("OK");
}

void uln_stop_write(struct usb_fifo *fifo)
{
    uln_printf("OK");
}

void uln_read_callback(struct usb_xfer *xfer, usb_error_t errno)
{
    uln_printf("OK");
}

void uln_write_callback(struct usb_xfer *xfer, usb_error_t errno)
{
    uln_printf("OK");
}

void uln_status_callback(struct usb_xfer *xfer, usb_error_t errno)
{
    uln_printf("OK");
}


/*

//BUS加载函数
static int uln_probe(device_t dev)
{
    struct usb_attach_arg *uaa = device_get_ivars(dev);
}
static int uln_attach(device_t dev);
static int uln_detach(device_t dev);

static device_method_t uln_methods[] = {
    DEVMETHOD(device_probe,     uln_probe),
    DEVMETHOD(device_attach,    uln_attach),
    DEVMETHOD(device_detach,    uln_detach),
    {0,0}
};

static driver_t uln_usb_driver ={
    "uln_usb",
    uln_methods,
    sizeof(struct uln_softc)
};

*/
